package org.jvm.nativemethod.methods.java.util;

import org.jvm.nativemethod.NativeMethodRegister;
import org.jvm.rtda.thread.*;

import java.lang.reflect.*;
import java.util.zip.Inflater;

/**
 * @author 海燕
 * @date 2023/2/26
 */
public class InflaterNativeMethod extends NativeMethodRegister {

    public static void init() throws NoSuchMethodException {
        register("java/util/zip/Inflater", "initIDs", "()V", InflaterNativeMethod.class.getDeclaredMethod("initIDs", Frame.class));
        register("java/util/zip/Inflater", "init", "(Z)J", InflaterNativeMethod.class.getDeclaredMethod("init", Frame.class));
        register("java/util/zip/Inflater", "inflateBytes", "(J[BII)I", InflaterNativeMethod.class.getDeclaredMethod("inflateBytes", Frame.class));

    }

    //    private static native void initIDs();
    public static void initIDs(Frame frame) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Method method = Inflater.class.getDeclaredMethod("initIDs");
        method.setAccessible(true);
        method.invoke(null);
    }

    //    private static native long init(boolean var0);
    public static void init(Frame frame) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        LocalVars localVars = frame.getLocalVars();
        boolean var0 = localVars.getInt(0) == 1;

        Method method = Inflater.class.getDeclaredMethod("init", boolean.class);
        method.setAccessible(true);
        long csize = (long) method.invoke(null, var0);

        frame.getOperandStack().pushLong(csize);
    }

    //    private native int inflateBytes(long var1, byte[] var3, int var4, int var5) throws DataFormatException;
    public static void inflateBytes(Frame frame) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        LocalVars localVars = frame.getLocalVars();
        long var0 = localVars.getLong(0);
        byte[] var3 = (byte[]) localVars.getRef(2).getData();
        int var4 = localVars.getInt(3);
        int var5 = localVars.getInt(4);

        Method method = Inflater.class.getDeclaredMethod("init", boolean.class);
        method.setAccessible(true);
        long csize = (long) method.invoke(null, var0);

        frame.getOperandStack().pushLong(csize);
    }

}
